package com.mju.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.connection.stream.StreamOffset;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StreamOperations;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mju.dao.SelectDurationMapper;
import com.mju.dao.StudentMapper;
import com.mju.dao.TeacherMapper;
import com.mju.exception.ServiceException;
import com.mju.model.Student;
import com.mju.model.Teacher;
import com.mju.model.dto.DurationDTO;
import com.mju.model.dto.SecurityUser;
import com.mju.service.TeacherService;

@Service
public class TeacherServiceImpl implements TeacherService {

	@Autowired
	private TeacherMapper teacherMapper;
	@Autowired
	private SelectDurationMapper durationMapper;
	
	@Autowired
	private StudentMapper  studentMapper;
	
	@Autowired
	private RedisTemplate<String,String> redisTemplate;	
	
	@Value("${custom.choiceRedisKey}")
	private String choiceRedisKey;
	
	@Override
	@Transactional
	public int batchInsert(List<Teacher> list) {
		teacherMapper.batchDelete(list);
		return teacherMapper.batchInsert(list);
	}
	
	@Override
	public List<Teacher> getList() {		
		return teacherMapper.selectList();
	}
		
	@Override
	public Page<Teacher> getList(int pageNo, int pageSize) {
		Page<Teacher> page=PageHelper.startPage(pageNo,pageSize);
		teacherMapper.selectList();
		return page;
	}

	@Override
	public DurationDTO selectDuaration() throws ServiceException{
		DurationDTO dto=durationMapper.selectDuaration();		 
		return dto;
	}
		
	@Override
	public Map<String, String> sendStreamMsg(String studentno, String teacher1, String teacher2)
			throws ServiceException {
			
		StreamOperations<String, String, String> opt= redisTemplate.opsForStream();

		if(checkMessage(opt, studentno))
			throw new ServiceException(604,"不能重复申报");
		
		Map<String,String> map = new HashMap<>();
		map.put("studentno",studentno);
		map.put("teacher1", teacher1);
		map.put("teacher2", teacher2);
		RecordId r=opt.add(choiceRedisKey, map);
		
		map.put("id",Long.toString(r.getTimestamp()) );		
		return map;
	}
	
	//例子，未做重复判断和时间有效性判断，暂由前端控制
	@Override
	public Map<String,String> sendStreamMsg(String teacher1,String teacher2) 
			throws ServiceException {				
		// 获取当前用户名
		SecurityContext context = SecurityContextHolder.getContext();
		SecurityUser sysUser=  (SecurityUser) context.getAuthentication().getPrincipal();
		String studentno=sysUser.getUserInfo().getStudentno();
		
		if(!sysUser.getUserInfo().getRole().equalsIgnoreCase("student")) {
			throw new ServiceException(605,"学生角色执行该操作！");
		}
			
		return this.sendStreamMsg(studentno, teacher1, teacher2);
	}
	
	@Override
	public List<Map<String,String>>  receiveMsg(int turnNum) throws ServiceException {		
		//判断时间,再学生选后，再执行		
		SecurityContext context = SecurityContextHolder.getContext();
		String teacherno= context.getAuthentication().getName();
		
		return this.receiveMsg(teacherno, turnNum);
	}
	
	@Override
	public List<Map<String, String>> receiveMsg(String teacherno, int turnNum) throws ServiceException {
		
		StreamOperations<String, String, String> opt= redisTemplate.opsForStream();
		List<MapRecord<String,String,String>> result=					
				opt.read(StreamOffset.fromStart(choiceRedisKey));
		
		List<Map<String,String>> retList=new ArrayList<>();
				
		for(MapRecord<String,String,String> x:result) {
			String teacher;
			if(turnNum==1) {
				teacher=x.getValue().get("teacher1");
				if(!teacher.equals(teacherno)) continue;
			}
			if(turnNum==2) {
				teacher=x.getValue().get("teacher2");
				if(!teacher.equals(teacherno)) continue;
			}
			Map<String,String> retMap=new HashMap<>();
			
			retMap.put("id",x.getId().toString());
			retMap.put("time",Long.toString(x.getId().getTimestamp()));
			String studentno=x.getValue().get("studentno");
			retMap.put("studentno",studentno);
			//获取学生姓名，学生班级
			Student student=studentMapper.selectByPrimaryKey(studentno);
			retMap.put("studentname",student.getStudentname());
			retMap.put("classname", student.getClassname());
			retList.add(retMap);
		}
		return retList;
	}
	
	//判断该学生是否已经在队列中存在
	private boolean checkMessage(StreamOperations<String, String, String> opt,String studentNo) {
		
		List<MapRecord<String,String,String>> result=					
				opt.read(StreamOffset.fromStart(choiceRedisKey));
//		
//		List<Map<String,String>> retList=new ArrayList<>();
				
		for(MapRecord<String,String,String> x:result) {
			String no=x.getValue().get("studentno");
			if(studentNo.equals(no)) return true;
		}
		return false;
	}

	@Override
	public Teacher getTeacherById() throws ServiceException{
		SecurityContext context = SecurityContextHolder.getContext();
		String teacherno= context.getAuthentication().getName();
		
		return this.getTeacherById(teacherno);
	}
	
	@Override
	public Teacher getTeacherById(String teacherno) throws ServiceException{
		
		Teacher teacher=teacherMapper.selectByPrimaryKey(teacherno);
		if(teacher==null)
			throw new ServiceException(605, "无该教师");
		return teacher;
	}
}
